using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Scenario_Editor.WR2TerrainLoader
{
    class QADFile
    {
        public List<BlockInfo> blockInfos;
        public List<ObjectPropertie> objectProperties;
        List<CollisionBlock> collisionBlocks;
        PointerTable pointerTable;
        public List<SurfaceChunk> surfaceChunks;
        List<WR2Surface> surfaces;
        List<Object> objects;
        List<Light> lights;
        List<Ground> grounds;
        List<Sound> sounds;
        List<ObjectName> textureNames;
        List<ObjectName> objectNames;

        uint scenarioWidth          = 0;
        uint scenarioLength         = 0; 
        uint cellsX                 = 0;
        uint cellsY                 = 0;
        uint numberOfPolygons       = 0;
        uint collisionLength        = 0;
        ushort x1                   = 0;
        ushort x2                   = 0;
        ushort x3                   = 0;
        ushort _NoIdea              = 0;

        public QADFile()
        {
            this.textureNames = new List<ObjectName>();
            this.objectNames = new List<ObjectName>();
            this.objectProperties = new List<ObjectPropertie>();
            this.blockInfos = new List<BlockInfo>();
            this.pointerTable = new PointerTable();
            this.collisionBlocks = new List<CollisionBlock>();
            this.surfaceChunks = new List<SurfaceChunk>();
            this.surfaces = new List<WR2Surface>();
            this.objects = new List<Object>();
            this.lights = new List<Light>();
            this.grounds = new List<Ground>();
            this.sounds = new List<Sound>();
        }


        public static QADFile FromFile(string filename)
        {
            QADFile qadFile = new QADFile();
            FileStream fs = new FileStream(filename, FileMode.Open);
            BinaryReader br = new BinaryReader(fs);

            br.BaseStream.Position = 0;

            qadFile.scenarioWidth = br.ReadUInt32(); //scenarioWidth
            qadFile.scenarioLength = br.ReadUInt32(); //Scenario length
            qadFile.cellsX = br.ReadUInt32(); //CellSizeX
            qadFile.cellsY = br.ReadUInt32(); //CellSizeY
            uint totalBlocks = br.ReadUInt32(); //TotalBlocks
            uint surfaceChunks = br.ReadUInt32(); //total Surface chunks in percent
            int numberOftextures = br.ReadInt32();//Textures?? each block 32 bytes
            uint numberOfObjects = br.ReadUInt32(); //object files each block 116 bytes
            qadFile.numberOfPolygons = br.ReadUInt32(); //total polys
            int numberOfSurfaces = br.ReadInt32(); //Textures??
            int numberOfObjectInstances = br.ReadInt32(); //object instances
            int numberOfGrounds = br.ReadInt32(); //grounds
            qadFile.collisionLength = br.ReadUInt32(); //collisionLength
            int numerOfLighs = (int)br.ReadInt16(); //Lights
            qadFile.x1 = br.ReadUInt16(); //x1 MAterial Assignment
            qadFile.x2 = br.ReadUInt16(); //x2
            qadFile.x3 = br.ReadUInt16(); //x3
            int numberOfSounds = (int)br.ReadUInt16(); //sounds
            qadFile._NoIdea = br.ReadUInt16(); //sounds

            // Load Texture Names Textures
            for (int i = 0; i < numberOftextures; i++)
            {
                qadFile.textureNames.Add(new ObjectName(br.ReadChars(32)));
            }

            //object names
            for (int i = 0; i < numberOfObjects; i++)
            {
                qadFile.objectNames.Add(new ObjectName(br.ReadChars(32)));
            }

            // Load Object Properties
            for (int i = 0; i < numberOfObjects; i++)
            {
                qadFile.objectProperties.Add(ObjectPropertie.FromStream(br, qadFile.objectNames[i].ToString()));
            }

            // BlockInfo
            for (int i = 0; i < totalBlocks; i++)
            {
                qadFile.blockInfos.Add(BlockInfo.FromStream(br));
            }

            // Load the offsets from the collisions blocks            
            qadFile.pointerTable.FromStream(br, (int)totalBlocks);

            //Load the collisions Blocks
            qadFile.collisionBlocks = CollisionBlock.FromStream(br, qadFile.collisionLength, qadFile.pointerTable);

            //Load the surface Chunks
            for (int i = 0; i < surfaceChunks; i++)
            {
                qadFile.surfaceChunks.Add(SurfaceChunk.FromStream(br));
            }

            //Load the surfaces
            for (int i = 0; i < numberOfSurfaces; i++)
            {
                qadFile.surfaces.Add(WR2Surface.FromStream(br));
            }

            //Load the objects
            for (int i = 0; i < numberOfObjectInstances; i++)
            {
                qadFile.objects.Add(Object.FromStream(br));
            }

            //Load the Lights
            for (int i = 0; i < numerOfLighs; i++)
            {
                qadFile.lights.Add(Light.FromStream(br));
            }

            //Load the Grounds
            for (int i = 0; i < numberOfGrounds; i++)
            {
                qadFile.grounds.Add(Ground.FromStream(br));
            }

            // Load X1 Block
            X1Block x1Block = new X1Block(br);

            //Load the Sounds
            for (int i = 0; i < numberOfSounds; i++)
            {
                qadFile.sounds.Add(Sound.FromStream(br));
            }



            return qadFile;
        }

        internal void Save(string filename)
        {


            FileStream fs = new FileStream(filename, FileMode.Create);
            BinaryWriter bw = new BinaryWriter(fs);

            try
            {
                bw.Write(this.scenarioWidth);//= br.ReadUInt32(); //scenarioWidth
                bw.Write(this.scenarioLength);// = br.ReadUInt32(); //Scenario length
                bw.Write(this.cellsX);// = br.ReadUInt32(); //CellSizeX
                bw.Write(this.cellsY);// = br.ReadUInt32(); //CellSizeY
                bw.Write(this.cellsX * this.cellsY); //uint totalBlocks =// br.ReadUInt32(); //TotalBlocks
                bw.Write((uint)this.surfaceChunks.Count);// uint surfaceChunks = br.ReadUInt32(); //total Surface chunks in percent
                bw.Write((uint)this.textureNames.Count);// int numberOftextures = br.ReadInt32();//Textures?? each block 32 bytes
                bw.Write((uint)this.objectProperties.Count);// uint numberOfObjects = br.ReadUInt32(); //object files each block 116 bytes
                bw.Write(this.numberOfPolygons);//= br.ReadUInt32(); //total polys
                bw.Write((uint)this.surfaces.Count);// int numberOfSurfaces = br.ReadInt32(); //Textures??
                bw.Write((uint)this.objects.Count);// int numberOfObjectInstances = br.ReadInt32(); //object instances
                bw.Write((uint)this.grounds.Count);// int numberOfGrounds = br.ReadInt32(); //grounds
                bw.Write((uint)this.collisionLength);// qadFile.collisionLength = br.ReadUInt32(); //collisionLength
                bw.Write((ushort)this.lights.Count);// int numerOfLighs = (int)br.ReadInt16(); //Lights
                bw.Write((ushort)this.x1);//= br.ReadUInt16(); //x1 MAterial Assignment
                bw.Write((ushort)this.x2);// qadFile.x2 = br.ReadUInt16(); //x2
                bw.Write((ushort)this.x3);// qadFile.x3 = br.ReadUInt16(); //x3
                bw.Write((ushort)this.sounds.Count);// int numberOfSounds = (int)br.ReadUInt16(); //sounds
                bw.Write((ushort)this._NoIdea);// qadFile._NoIdea = br.ReadUInt16(); //sounds

                // Load Texture Names Textures
                for (int i = 0; i < this.textureNames.Count; i++)
                {
                    this.textureNames[i].Save(bw);// qadFile.textureNames.Add(new ObjectName(br.ReadChars(32)));
                }

                //object names
                for (int i = 0; i < this.objectNames.Count; i++)
                {
                    this.objectNames[i].Save(bw);// qadFile.objectNames.Add(new ObjectName(br.ReadChars(32)));
                }

                // Load Object Properties
                for (int i = 0; i < this.objectProperties.Count; i++)
                {
                    this.objectProperties[i].Save(bw);// qadFile.objectProperties.Add(ObjectPropertie.FromStream(br, qadFile.objectNames[i].ToString()));
                }

                // BlockInfo
                for (int i = 0; i < (int)(this.cellsX * this.cellsY); i++)
                {
                    this.blockInfos[i].Save(bw);// qadFile.blockInfos.Add(BlockInfo.FromStream(br));
                }

                // Load the offsets from the collisions blocks            
                this.pointerTable.Save(bw, this.collisionBlocks, this.blockInfos.Count);   // qadFile.pointerTable.FromStream(br, (int)totalBlocks);

                //Load the collisions Blocks
                for (int i = 0; i < this.collisionBlocks.Count; i++)
                {
                    this.collisionBlocks[i].Save(bw); //= CollisionBlock.FromStream(br, qadFile.collisionLength, qadFile.pointerTable);

                }

                //Load the surface Chunks
                for (int i = 0; i < this.surfaceChunks.Count; i++)
                {
                    this.surfaceChunks[i].Save(bw);// qadFile.surfaceChunks.Add(SurfaceChunk.FromStream(br));
                }

                //Load the surfaces
                for (int i = 0; i < this.surfaces.Count; i++)
                {
                    this.surfaces[i].SaveToStream(bw);// qadFile.surfaces.Add(WR2Surface.FromStream(br));
                }

                //Load the objects
                for (int i = 0; i < this.objects.Count; i++)
                {
                    this.objects[i].Save(bw);// qadFile.objects.Add(Object.FromStream(br));
                }

                //Load the Lights
                for (int i = 0; i < this.lights.Count; i++)
                {
                    this.lights[i].Save(bw);// qadFile.lights.Add(Light.FromStream(br));
                }

                //Load the Grounds
                for (int i = 0; i < this.grounds.Count; i++)
                {
                    this.grounds[i].Save(bw);// qadFile.grounds.Add(Ground.FromStream(br));
                }

                // Load X1 Block
                //X1Block x1Block = new X1Block(br);

                for (int i = 0; i < 64; i++)//64 is the max number of Polygon blocks
                {
                    bw.Write((int)0);
                    bw.Write((int)0);
                }

                //Load the Sounds
                for (int i = 0; i < this.sounds.Count; i++)
                {
                    this.sounds[i].Save(bw);// qadFile.sounds.Add(Sound.FromStream(br));
                }
            }
            catch
            {
 
            }
            bw.Close();
            fs.Close();
           

        }
    }
}
